package com.terrace.controller.system;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.terrace.core.common.model.ResultData;
import com.terrace.db.system.mapper.entity.Organization;
import com.terrace.db.system.mapper.entity.Role;
import com.terrace.db.system.mapper.entity.User;
import com.terrace.core.common.model.UserInfo;
import com.terrace.db.system.mapper.entity.UserOrganization;
import com.terrace.db.system.service.OrganizationService;
import com.terrace.db.system.service.RoleService;
import com.terrace.db.system.service.UserService;
import com.terrace.core.mybatis.entity.Pagination;
import com.terrace.core.utils.ApplicationContextUtil;
import com.terrace.core.utils.PasswordUtils;
import com.terrace.core.utils.UUIDGenerator;
import com.terrace.web.annotation.Logs;
import com.terrace.web.constant.GlobalsConstant;
import com.terrace.web.model.DataGrid;

/**
 * 用户管理
 * @author jiangyg
 *
 */
@Controller
@Scope("prototype")
@RequestMapping("/user")
public class UserController {
	
	/**
	 * 日志
	 */
	private static final Logger logger = LoggerFactory.getLogger(UserController.class);
	
	private static final String MESSAGE_TYPE = "用户";
	
	@Autowired
	private UserService userService;
	
	/**
	 * 用户管理界面
	 * @param request
	 * @return
	 */
	@RequestMapping
	public ModelAndView userList(HttpServletRequest request){
		return new ModelAndView("system/user/userList");
	}
	
	/**
	 * 用户信息
	 * @return
	 */
	@RequestMapping(params = "userInfo")
	public ModelAndView userInfoView(HttpServletRequest request) {
		Session session =SecurityUtils.getSubject().getSession();
		UserInfo userInfo = (UserInfo) session.getAttribute(GlobalsConstant.USER_SESSION_KEY);
		if (userInfo != null) {
			userInfo = userService.selectUserInfoByAccount(userInfo.getUserAccount());
			request.setAttribute("userInfo", userInfo);
		}
		return new ModelAndView("system/user/userInfo");
	}
	
	/**
	 * 数据表格
	 * @param request
	 * @param pagination
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "datagrid")
	@RequiresPermissions("system:user:view")
	public DataGrid<User> datagrid(User user, Pagination<User> pagination, HttpServletRequest request) {
		DataGrid<User> dataGrid = new DataGrid<User>();
		dataGrid.setPagination(userService.selectUserForPagination(pagination, user));
		return dataGrid;
	}
	
	/**
	 * 角色下的用户信息数据表格
	 * @param request
	 * @param pagination
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "users-role-datagrid")
	@RequiresPermissions("system:usersinrole:view")
	public DataGrid<User> usersInRoleDatagrid(@RequestParam("roleId") String roleId, User user, Role role, Pagination<User> pagination, HttpServletRequest request) {
		DataGrid<User> dataGrid = new DataGrid<User>();
		user.setId(null);
		role.setId(roleId);
		dataGrid.setPagination(userService.selectUsersInRoleForPagination(pagination, user, role));
		return dataGrid;
	}
	
	/**
	 * 在角色下不存在的用户列表分页查询
	 * @param roleId
	 * @param user
	 * @param pagination
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "non-exist-users-role-datagrid")
	@RequiresPermissions("system:nonexistusersinrole:view")
	public DataGrid<User> usersInRoleDatagrid(@RequestParam("roleId") String roleId, User user, Pagination<User> pagination, HttpServletRequest request) {
		DataGrid<User> dataGrid = new DataGrid<User>();
		dataGrid.setPagination(userService.selectNonExistUsersInRoleForPagination(pagination, roleId, user));
		return dataGrid;
	}
	
	/**
	 * 组织下的用户信息分页查询
	 * @param orgId
	 * @param user
	 * @param pagination
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "users-org-datagrid")
	@RequiresPermissions("system:usersinorg:view")
	public DataGrid<User> usersInOrgDatagrid(@RequestParam("orgId") String orgId, User user, Pagination<User> pagination, HttpServletRequest request) {
		DataGrid<User> dataGrid = new DataGrid<User>();
		Organization org = new Organization();
		org.setId(orgId);
		dataGrid.setPagination(userService.selectUsersInOrgForPagination(pagination, user, org));
		return dataGrid;
	}
	
	/**
	 * 未指定组织的用户信息分页查询
	 * @param user
	 * @param pagination
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "users-notin-org-datagrid")
	@RequiresPermissions("system:usersnotinorg:view")
	public DataGrid<User> usersNotInOrgDatagrid(User user, Pagination<User> pagination, HttpServletRequest request) {
		DataGrid<User> dataGrid = new DataGrid<User>();
		dataGrid.setPagination(userService.selectUsersNotInOrgForPagination(pagination, user));
		return dataGrid;
	}
	
	/**
	 * 新增或者修改页面
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "addorupdate")
	public ModelAndView addorupdate(String id, HttpServletRequest request){
		if (StringUtils.isNotBlank(id)) {
			User user = userService.selectUserById(id);
			request.setAttribute("user", user);
		}
		return new ModelAndView("system/user/user");
	}
	
	/**
	 * 保存用户
	 * @param user
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequiresRoles(GlobalsConstant.Roles.ADMIN)
	@RequestMapping(params = "saveOrUpdate")
	@RequiresPermissions("system:user:save")
	@Logs(depict = "保存用户", type = GlobalsConstant.LogTypes.SYS_USER)
	public ResultData saveOrUpdate(User user, HttpServletRequest request) {
		ResultData rd = new ResultData();
		if (StringUtils.isBlank(user.getId())) {
			// 组织
			OrganizationService orgService = ApplicationContextUtil.getContext().getBean(OrganizationService.class);
			String orgId = request.getParameter("orgId");
			if (StringUtils.isBlank(orgId)) {
				return rd.failObjs("13105");
			}
			Organization org = orgService.selectOrganizationById(orgId);
			if (org == null) {
				return rd.failObjs("13103", "组织机构代码");
			}
			
			// 保存用户信息
			user.setId(UUIDGenerator.generate());
			String password = user.getUserPwd();
			String salt = PasswordUtils.getSaltRands();
			user.setUserPwd(PasswordUtils.encrypt(user.getUserAccount(), password, salt.getBytes()));
			user.setSalt(salt);
			userService.saveUserSelective(user);
			
			// 保存用户组织信息
			UserOrganization userOrganization = new UserOrganization();
			userOrganization.setId(UUIDGenerator.generate());
			userOrganization.setOrganization(org);
			userOrganization.setUser(user);
			orgService.saveUserOrganization(userOrganization);
			
			rd.successObjs("10001", MESSAGE_TYPE);
		} else {
			User temp = userService.selectUserById(user.getId());
			if (temp == null) {
				return rd.failObjs("13103", MESSAGE_TYPE);
			}
			// 只修改用户信息，不修改密码和账号
			user.setUserAccount(null);
			user.setUserPwd(null);
			user.setSalt(null);
			userService.updateUserSelectiveById(user);
			rd.successObjs("10002", MESSAGE_TYPE);
		}
		return rd;
	}
	
	/**
	 * 删除用户
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "delete")
	@RequiresRoles(GlobalsConstant.Roles.ADMIN)
	@RequiresPermissions("system:user:delete")
	@Logs(depict = "删除用户", type = GlobalsConstant.LogTypes.SYS_USER)
	public ResultData delete(@RequestParam(value = "id") String userId, HttpServletRequest request) {
		ResultData rd = new ResultData();
		User user = userService.selectUserById(userId);
		if (user == null) {
			return rd.failObjs("13103", MESSAGE_TYPE);
		}
		
		// 用户是否在机构中
		OrganizationService organizationService = ApplicationContextUtil.getContext().getBean(OrganizationService.class);
		List<Organization> orgList = organizationService.selectOrganizationsByUserId(userId);
		if(orgList != null && orgList.size() > 0) {
			StringBuffer errors = new StringBuffer();
			errors.append("用户[" + user.getUserAccount() + "]已存在[");
			for (int o = 0; o < orgList.size(); o++) {
				errors.append(orgList.get(o).getOrgName());
				if(o != orgList.size() - 1) {
					errors.append(",");
				}
			}
			errors.append("]机构中，想要删除用户请先删除关联关系！");
			rd.setStatus("13000");
			rd.setMessage(errors.toString());
			return rd;
		}
		
		// 用户是否在角色中
		RoleService roleService = ApplicationContextUtil.getContext().getBean(RoleService.class);
		List<Role> roleList = roleService.selectRoleByUserId(userId);
		if(roleList != null && roleList.size() > 0) {
			StringBuffer errors = new StringBuffer();
			errors.append("用户[" + user.getUserAccount() + "]已存在[");
			for (int r = 0; r < roleList.size(); r++) {
				errors.append(roleList.get(r).getRoleName());
				if(r != roleList.size() - 1) {
					errors.append(",");
				}
			}
			errors.append("]角色中，想要删除用户请先删除关联关系！");
			rd.setStatus("13000");
			rd.setMessage(errors.toString());
			return rd;
		}
		
		int result = userService.deleteUserById(userId);
		if (result != 1) {
			rd.failObjs("13102", MESSAGE_TYPE);
		} else {
			rd.successObjs("10003", MESSAGE_TYPE);
		}
		return rd;
	}
	
	/**
	 * 修改密码页面
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "changePassword")
	public ModelAndView changePassword(HttpServletRequest request) {
		return new ModelAndView("main/cpwd");
	}
	
	/**
	 * 保存新密码
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "saveNewPassword")
	@Logs(depict = "保存新密码", type = GlobalsConstant.LogTypes.SYS_USER)
	public ResultData saveNewPassword(@RequestParam(value = "oldPassword") String oldPassword,
			@RequestParam(value = "newPassword") String newPassword,
			@RequestParam(value = "newPasswordAgain") String newPasswordAgain, HttpServletRequest request) {
		ResultData rd = new ResultData();
		if (!StringUtils.equals(newPassword, newPasswordAgain)) {
			return rd.failObjs("13006", "两次密码");
		}
		Session session = SecurityUtils.getSubject().getSession();
		UserInfo userInfo = (UserInfo) session.getAttribute(GlobalsConstant.USER_SESSION_KEY);
		User user = userService.selectUserByAccount(userInfo.getUserAccount());
		String password = PasswordUtils.encrypt(user.getUserAccount(), oldPassword, user.getSalt().getBytes());
		if (!StringUtils.equals(password, user.getUserPwd())) {
			return rd.failObjs("13005", "密码");
		}
		String newSalt = PasswordUtils.getSaltRands();
		User modifiedUserInfo = new User();
		modifiedUserInfo.setId(user.getId());
		modifiedUserInfo.setUserPwd(PasswordUtils.encrypt(user.getUserAccount(), newPassword, newSalt.getBytes()));
		modifiedUserInfo.setSalt(newSalt);
		userService.updateUserSelectiveById(modifiedUserInfo);
		return rd.successObjs("10002", "新密码");
	}
	
	/**
	 * 重置密码
	 * @param request
	 * @return
	 */
	@RequestMapping(params = "resetPassword")
	public ModelAndView resetPassword(@RequestParam("id") String userId, HttpServletRequest request) {
		request.setAttribute("userId", userId);
		return new ModelAndView("system/user/resetPwd");
	}
	
	/**
	 * 重置新密码
	 * @param oldPassword
	 * @param newPassword
	 * @param newPasswordAgain
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequiresRoles(GlobalsConstant.Roles.ADMIN)
	@RequestMapping(params = "resetNewPassword")
	@RequiresPermissions("system:user:reset:password")
	@Logs(depict = "重置新密码", type = GlobalsConstant.LogTypes.SYS_USER)
	public ResultData resetNewPassword(@RequestParam(value = "userId") String userId,
			@RequestParam(value = "newPassword") String newPassword,
			@RequestParam(value = "newPasswordAgain") String newPasswordAgain, HttpServletRequest request) {
		ResultData rd = new ResultData();
		if (!StringUtils.equals(newPassword, newPasswordAgain)) {
			return rd.failObjs("13006", "两次密码");
		}
		User user = userService.selectUserById(userId);
		if (user == null) {
			logger.error("重置新密码出错：未找到用户id[" + userId + "]对应的用户信息。");
			return rd.failObjs("13105");
		}
		String newSalt = PasswordUtils.getSaltRands();
		User modifiedUserInfo = new User();
		modifiedUserInfo.setId(user.getId());
		modifiedUserInfo.setUserPwd(PasswordUtils.encrypt(user.getUserAccount(), newPassword, newSalt.getBytes()));
		modifiedUserInfo.setSalt(newSalt);
		userService.updateUserSelectiveById(modifiedUserInfo);
		return rd.successObjs("10009", "重置新密码");
	}

}
